<template>
  <div
    ref="root"
    :class="props.class"
    style="visibility: hidden; position: absolute"
  >
    <slot />
  </div>
</template>

<script setup lang="ts">
import { nextTick, onBeforeUnmount, onMounted, ref, shallowRef } from "vue";
import type { Plugin } from "@tiptap/pm/state";
import type { Editor } from "@tiptap/core";
import type { Node } from "@tiptap/pm/model";
import type { ComputePositionConfig, VirtualElement } from "@floating-ui/dom";
import {
  DragHandlePlugin,
  dragHandlePluginDefaultKey,
} from "../../../../extensions/drag-handle/drag-handle-plugin";
import { defaultComputePositionConfig } from "../../../../extensions/drag-handle/drag-handle";

export interface DragHandleProps {
  editor: Editor;
  pluginKey?: string | any;
  class?: string;
  computePositionConfig?: ComputePositionConfig;
  getReferencedVirtualElement?: () => VirtualElement | null;
  onNodeChange?: (data: {
    node: Node | null;
    editor: Editor;
    pos: number;
  }) => void;
  onElementDragStart?: (e: DragEvent) => void;
  onElementDragEnd?: (e: DragEvent) => void;
}

defineOptions({
  name: "DragHandle",
});

const props = withDefaults(defineProps<DragHandleProps>(), {
  pluginKey: dragHandlePluginDefaultKey,
  class: "drag-handle",
  computePositionConfig: () => ({}),
});

const root = ref<HTMLElement | null>(null);
const pluginHandle = shallowRef<{ plugin: Plugin; unbind: () => void } | null>(
  null
);

onMounted(async () => {
  await nextTick();

  const {
    editor,
    pluginKey,
    onNodeChange,
    onElementDragEnd,
    onElementDragStart,
    computePositionConfig,
    getReferencedVirtualElement,
  } = props;

  if (!root.value) {
    return;
  }
  if (!props.editor || props.editor.isDestroyed) {
    return;
  }

  const init = DragHandlePlugin({
    editor,
    element: root.value,
    pluginKey,
    computePositionConfig: {
      ...defaultComputePositionConfig,
      ...computePositionConfig,
    },
    getReferencedVirtualElement,
    onNodeChange,
    onElementDragStart,
    onElementDragEnd,
  });

  pluginHandle.value = init;

  // TipTap Vue 3 编辑器支持 registerPlugin 方法
  // @ts-ignore - TipTap Vue 3 内部方法
  if (props.editor.registerPlugin) {
    console.log("注册 drag-handle 插件");
    props.editor.registerPlugin(init.plugin);
  } else if (props.editor.view) {
    // 如果没有 registerPlugin，直接添加到 ProseMirror view 的插件系统
    // 这需要通过扩展系统来处理，暂时使用 fallback
    console.warn(
      "Editor does not support registerPlugin, plugin may not work correctly"
    );
  }
});

onBeforeUnmount(() => {
  if (!pluginHandle.value) {
    return;
  }

  pluginHandle.value.unbind?.();

  // TipTap Vue 3 编辑器支持 unregisterPlugin 方法
  if (props.editor && !props.editor.isDestroyed) {
    // @ts-ignore - TipTap Vue 3 内部方法
    if (props.editor.unregisterPlugin) {
      props.editor.unregisterPlugin(props.pluginKey);
    }
  }

  pluginHandle.value = null;
});
</script>
